 ///
 /// @file    3_Point.cc
 /// @author  lemon(haohb13@gmail.com)
 /// @date    2023-04-21 10:21:04
 ///
 
#include <iostream>
using std::cout;
using std::endl;

class Point
{
public:
	Point(int ix = 0, int iy = 0)
	: _ix(ix)
	, _iy(iy)
	{
		cout << "Point(int =0,int=0)" << endl;
	}

	//即使不显式提供的情况下，
	//系统会自动提供一个拷贝构造函数
	Point(Point & rhs)
	: _ix(rhs._ix)
	, _iy(rhs._iy)
	{
		cout << "Point(const Point&)" << endl;
	}

	void print() 
	{
		cout << "(" << _ix
			 << "," << _iy
			 << ")" << endl;
	}

	~Point()
	{
		cout << "~Point()" << endl;
	}

private:
	int _ix;
	int _iy;
};

void func1(Point pt)
{
	cout << "func1()" << endl;	
	pt.print();
}

void test1()
{
	Point p(11, 12);
	func1(p);
}

//存在编译器的优化操作
//为了看到拷贝构造函数的调用，需要加上一个编译选项
// -fno-elide-constructors
Point func2()
{
	Point p(21, 22);
	cout << "p:";
	p.print();
	return p;
}

void test2()
{
	//Point & rhs = func2();
	//当func2()执行完毕之后，会产生一个临时对象
	//该临时对象是一个右值,
	//而拷贝构造函数的参数是 Point &rhs
	//不能绑定到右值的
	&func2();//无法取地址, 右值
	Point p1 = func2();
	func2();//右值
}

void test3()
{
	//左值：能够进行取地址操作的表达式
	//右值：不能够取地址的表达式
	
	Point p(21, 22);
	&p;//左值

	//&10;//字面值常量, 右值

	int & ref = 10;//error  非const左值引用
	const int & ref2 = 10;//ok
	&ref2;//可以取地址，是一个左值

	//匿名对象的生命周期只在这一行
	//执行完毕之后，马上会被销毁
	//临时对象
	const Point & ref3 = Point(31,32);//匿名对象, 也是右值

	cout << "exit test3()" << endl;
}

void test0() 
{
	int a = 1;
	int b = a;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;

	Point pt1(1, 2);
	//在这里是调用了拷贝构造函数
	//Point pt2 = pt1;
	Point pt2(pt1);
	cout << "pt1:";
	pt1.print();

	cout << "pt2:";
	pt2.print();

	Point pt3(11, 12);
	cout << "pt3:";
	pt3.print();

} 
 
int main(void)
{
	/* test0(); */
	/* test1(); */
	/* test2(); */
	test3();
	return 0;
}
